using iTron;
using iTron.Model;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTron.Model.Player;
using iTron.View;
using iTron.Model.GridItems;

namespace iTron.Controller
{
    public class GameController
    {
        public Grid grid;
        GridGUI gridgui;
        List<Player> players = new List<Player>();
        public bool isGameOver { get; set; }
        int gameStatus { get; set; }
        GameTime gameTime;

        public GameController(ContentManager cm)
        {
            this.gameStatus = Utils.GAMESTATUS_NOTSTARTED;
            this.grid = new Grid();
            this.gridgui = new GridGUI(cm, grid);
        }

        public void addPlayer(Player player)
        {
            players.Add(player);
            gridgui.addPlayer(player);
        }

        public void driveBike(Player player)
        {
            for (int i = 0; i < Grid.GRID_HEIGHT; i++)
            {
                for (int j = 0; j < Grid.GRID_WIDTH; j++)
                {
                    if (grid.grid[i, j].isBike && grid.grid[i, j].playerID == player.ID)
                    {
                        ((Bike)grid.grid[i, j]).drive();

                        // Player moved up
                        if (grid.grid[i, j].y < 0)
                        {
                            if (i - 1 < 0)
                            {
                                handleCollision(player.ID);
                                return;
                            }
                            if (grid.grid[i - 1, j].isBike || grid.grid[i - 1, j].isTrail)
                            {
                                handleCollision(player.ID);
                                return;
                            }

                            Bike bike = (Bike)grid.grid[i, j];
                            grid.grid[i, j] = new Trail(player.ID, bike.directionFrom, bike.directionTo);
                            grid.grid[i - 1, j] = new Bike(Utils.DIRECTION_TOP, player.ID, (GridItem.GRIDITEM_WIDTH / 2) - 1, GridItem.GRIDITEM_HEIGHT - 1);
                        }
                        // Player moved right
                        else if (grid.grid[i, j].x >= GridItem.GRIDITEM_WIDTH)
                        {
                            if (j + 1 >= Grid.GRID_WIDTH)
                            {
                                handleCollision(player.ID);
                                return;
                            }
                            if (grid.grid[i, j + 1].isBike || grid.grid[i, j + 1].isTrail)
                            {
                                handleCollision(player.ID);
                                return;
                            }

                            Bike bike = (Bike)grid.grid[i, j];
                            grid.grid[i, j] = new Trail(player.ID, bike.directionFrom, bike.directionTo);
                            grid.grid[i, j + 1] = new Bike(Utils.DIRECTION_RIGHT, player.ID, 0, (GridItem.GRIDITEM_HEIGHT / 2) - 1);
                        }
                        // Player moved down
                        else if (grid.grid[i, j].y >= GridItem.GRIDITEM_HEIGHT)
                        {
                            if (i + 1 >= Grid.GRID_HEIGHT)
                            {
                                handleCollision(player.ID);
                                return;
                            }
                            if (grid.grid[i + 1, j].isBike || grid.grid[i + 1, j].isTrail)
                            {
                                handleCollision(player.ID);
                                return;
                            }

                            Bike bike = (Bike)grid.grid[i, j];
                            grid.grid[i, j] = new Trail(player.ID, bike.directionFrom, bike.directionTo);
                            grid.grid[i + 1, j] = new Bike(Utils.DIRECTION_BOTTOM, player.ID, (GridItem.GRIDITEM_WIDTH / 2) - 1, 0);
                        }
                        // Player moved left
                        else if (grid.grid[i, j].x < 0)
                        {
                            if (j - 1 < 0)
                            {
                                handleCollision(player.ID);
                                return;
                            }
                            if (grid.grid[i, j - 1].isBike || grid.grid[i, j - 1].isTrail)
                            {
                                handleCollision(player.ID);
                                return;
                            }

                            Bike bike = (Bike)grid.grid[i, j];
                            grid.grid[i, j] = new Trail(player.ID, bike.directionFrom, bike.directionTo);
                            grid.grid[i, j - 1] = new Bike(Utils.DIRECTION_LEFT, player.ID, GridItem.GRIDITEM_WIDTH - 1, (GridItem.GRIDITEM_HEIGHT / 2) - 1);
                        }
                    }
                }
            }
        }

        private void handleCollision(int player)
        {
            // Set player game over to true
            players[player - 1].isGameOver = true;
            // check if human is the player
            if (player == 1) isGameOver = true;

            if (!isGameOver)
            {
                // Remove bike and trail for player X
                for (int i = 0; i < Grid.GRID_HEIGHT; i++)
                {
                    for (int j = 0; j < Grid.GRID_WIDTH; j++)
                    {
                        if (grid.grid[i, j].isBike)
                        {
                            Bike bike = (Bike)grid.grid[i, j];
                            if (bike.playerID == player) grid.grid[i, j] = new Empty();
                        }
                        else if (grid.grid[i, j].isTrail)
                        {
                            Trail trail = (Trail)grid.grid[i, j];
                            if (trail.playerID == player) grid.grid[i, j] = new Empty();
                        }
                    }
                }

                // Remove player from game
                for (int i = 0; i < players.Count; i++)
                {
                    if (players[i].ID == player) players[i].isGameOver = true;
                }
            }
        }

        public bool isVictory() {
            for (int i = 1; i < players.Count; i++)
            {
                if (!players[i].isGameOver)
                    return false;
            }

            return true;
        }

        public void makeAction(Player player, int action)
        {
            switch (action)
            {
                case Utils.BUTTON_BOOST: // TODO: Is it working?
                    if (player.speed > Utils.SPEED_LOW) player.speed -= Utils.SPEED_LOW;
                    break;
                case Utils.BUTTON_BRAKE: // TODO: Is it working?
                    if (player.speed < Utils.SPEED_HIGH) player.speed += Utils.SPEED_LOW;
                    break;
                case Utils.BUTTON_LEFT: // TODO: Is it working?
                    player.nextAction = Utils.BUTTON_LEFT;
                    break;
                case Utils.BUTTON_RIGHT: // TODO: Is it working?
                    player.nextAction = Utils.BUTTON_RIGHT;
                    break;
            }
        }

        public void paint(SpriteBatch batch)
        {
            gridgui.draw(batch, grid.grid);
        }

        public void start()
        {
            // TODO: Ignite?
            this.gameStatus = Utils.GAMESTATUS_STARTED;
        }

        public void update(GameTime time)
        {
            this.gameTime = time;
            gridgui.update(time);

            if (!isGameOver)
            {
                // Player loop
                foreach (Player player in players)
                {
                    if (!player.isGameOver)
                    {
                        player.timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

                        if (player.timer > player.speed)
                        {
                            // Update trail
                            //grid.updateTrail(player);

                            // Take action
                            switch (player.nextAction)
                            {
                                case Utils.BUTTON_LEFT:
                                    grid.turnBike(player, Utils.DIRECTION_LEFT);
                                    break;
                                case Utils.BUTTON_RIGHT:
                                    grid.turnBike(player, Utils.DIRECTION_RIGHT);
                                    break;
                            }

                            driveBike(player);

                            // Reset
                            player.timer = 0;
                        }
                    }
                }
            }

            //grid.update();
        }
    }
}
